home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr47
/
wasm223.zip
/
OBJECT.DOC
< prev
next >
Wrap
Text File
|
1993-05-04
|
10KB
|
236 lines
Object File Macros
------------------
The macros defined in the file OBJECT.INC allow WASM to create
standard object modules that can be linked with object modules from
other languages. The primary limitations of these macros are that
external symbols cannot be referenced and there are certain
limitations in the way local data may be accessed.
I have successfully used these macros to produce WASM subroutines for
QuickBASIC version 4.0 (using LINK.EXE version 3.65), and Turbo C++
version 1.0 (using TLINK.EXE version 3.0).
General Layout
--------------
The format of a WASM object module consists of the INIT macro first,
all PUBLIC definitions, the BEGIN macro, all assembler code and data,
and finally the END macro. All assembler code and data must be
between the BEGIN and END macros. Example:
INCLUDE 'obj.inc'
INIT 'MYFILE.ASM', '_TEXT', 'CODE', ALIGN_BYTE+COMBINE_PUBLIC
PUBLIC MyProc1, '_MyProc1'
PUBLIC MyProc2, '_MyProc2'
BEGIN
MyProc1 PROC FAR
ret
ENDP
MyProc2 PROC FAR
ret
ENDP
END
The example above declares two public symbols using the 'C' naming
style (i.e. case sensitive with preceding underscores). The public
symbols reference the two procedures. The procedures are FAR, so the
C program must be compiled using the medium, large, or huge memory
models.
When these macros are used, the result of the assembly is a valid
object module and may be linked using LINK.EXE, TLINK.EXE, or other
compatible linker. For instance, the example above would be compiled
as follows:
WASM myfile myfile.obj
INIT Macro
----------
The INIT macro creates an object module header and defines the segment
in which to place the code and data. The syntax for INIT is:
INIT name, segment, class, segtype
The name is the name of the module. Most compilers use the name of
the source file (including the extension) to name an object module.
The segment is the name of the segment. Depending on the compiler and
the memory model, it might be necessary to place code or data in
specific segments. Compilers from Microsoft and Borland (and probably
most other vendors) place the code in segment '_TEXT' when using the
near code memory models (small and compact) and the data in segment
'_DATA' when using near data memory models (small and medium).
Usually any name is okay if the segment is private.
The class is the name of the segment class. The segment class
primarily affects the order of the segments. You should use either
'CODE' if you are defining public routines or 'DATA' if you are
defining public data. The class may be blank, in which case the
segment has no class:
INIT 'MYFILE.ASM', '_TEXT', , ALIGN_BYTE+COMBINE_PUBLIC
The segtype is the type of segment. There are two values that must be
added together for this argument, the alignment and combine type. The
possible alignment and combine values are:
ALIGN_BYTE byte aligned
ALIGN_WORD word aligned
ALIGN_PARA paragraph aligned
ALIGN_PAGE page aligned
COMBINE_PRIVATE private segment
COMBINE_PUBLIC public segment
COMBINE_STACK stack segment
COMBINE_COMMON common segment
If you wish to declare and access local data in the segment, it will
probably be necessary to create a paragraph aligned private segment.
Public procedures in private segments should be FAR and the language
must be compiled using a far code model -- either medium, large, or
huge. When a routine accesses data in a private segment, the current
code segment should be used:
BEGIN
MyProc1 PROC FAR
push ds
mov ax, cs ;load data segment from CS
mov ds, ax ;
mov ax, data ;now we can access data
pop ds
ret
ENDP
data DW ?
END
PUBLIC Macro
------------
The PUBLIC macro creates public symbol definitions. A symbol must be
public if it is to be used outside of the module. The syntax for
PUBLIC is:
PUBLIC symbol, name
The symbol is a symbol from the assembler code or data to be made
public. The name is the name to be used by other modules in accessing
the symbol. Example:
PUBLIC MyProc, 'MYPROC'
In this example, references to MYPROC in other modules will access the
symbol MyProc in this module.
Depending on the compiler and memory model, it may not be possible to
mix public references to code and data in one module.
BEGIN/END Macros
----------------
The BEGIN macro must appear before all code and data and the END macro
must follow all code and data. No code or data may appear outside of
the BEGIN and END macros. The END macro is usually the final
statement of the source file. BEGIN starts an object module data
record and sets the origin to zero. END finishes the data record and
creates a module end record.
Language Considerations
-----------------------
There are certain conventions that must be followed when writing
subroutines for high level languages:
1. The procedure type (NEAR or FAR) must match the memory model.
Procedures should be NEAR when using the small or compact memory
models. Procedures should be FAR when using the medium, large, or
huge memory models. Most languages that do not support explicit
memory models use far code segments, thus procedures should be FAR.
2. Most languages use one of two different naming and parameter
passing conventions, 'C' or 'pascal' (even languages are not C or
Pascal). 'C' routines should be given a case sensitive name with a
leading underscore, expect their parameters to be pushed on the
stack in reverse order, and not pop parameters when exiting.
'pascal' routines should be given a case insensitive name (all
capital letters), expect their parameters to be pushed on the stack
in the order they appear in the source, and must pop all parameters
when exiting.
Parameters are accessed via an offset from the stack pointer (SP).
This offset depends on the routine entry code and whether the
procedure is NEAR or FAR.
Example:
PUBLIC MyProc, 'MYPROC' ;'pascal' type public symbol
; PUBLIC MyProc, '_MyProc' ;'C' type public symbol
BEGIN
MyProc PROC NEAR ;might also be FAR
push bp
mov bp, sp ;get stack pointer
push di ;other regs to save
push ds ;
mov ax, [bp+4] ;first 'pascal' parameter, last 'C' parameter
;should be [BP+6] if FAR procedure
mov bx, [bp+6] ;next parameter
;should be [BP+8] if FAR procedure
;
; rest of MyProc
;
pop ds
pop di
pop bp
ret 4 ;fix stack if 'pascal', otherwise just RET
ENDP
The registers that must be saved by an assembler routine varies from
language to language. Most compiler manuals describe the steps
necessary in writing and calling assembler routines. It may also be
useful to look at a link map from the compiler and study an executable
program from the compiler using a debugger.
You can write object modules for Turbo Pascal if you place the code in
the segment CODE and leave the class blank. Since Turbo Pascal (at
least version 5.5) ignores the alignment and combine values, local
data cannot be accessed.
WASM Library Files
------------------
The WASM library files may be used in modules as long as certain
conditions are met. All library files assume that DS=ES=CS. Library
files that require STACK.ASM assume that SS=DS=ES=CS, thus a separate
stack must be set up. Some of the library files won't work in
modules, like PARMS.ASM, because the current segment is assumed to be
the PSP segment. Since the library files produce code and data, the
library INCLUDE statements must be between the BEGIN and END. Several
of the library files have startup code that should be executed, so you
might want to place the library INCLUDE statements within a special
initialization routine. Note that WASM routines cannot call WASM
routines in other modules because WASM object modules do not support
external symbols.